package com.upcode.weighing.gateway.controller;

import com.google.common.collect.ImmutableMap;
import com.upcode.weighing.gateway.util.ClientRequestInfoUtil;

import io.swagger.annotations.Api;
import org.apache.commons.codec.binary.Base64;
import org.orclight.java.util.captha.CaptchaClient;
import org.orclight.java.util.captha.bean.CaptchaBean;
import org.orclight.java.util.captha.strategy.ChineseCaptchaStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author alex
 * @date 2019/4/9
 */
@RestController
public class CaptchaController {

    private static final Logger LOGGER = LoggerFactory.getLogger(CaptchaController.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CaptchaClient captchaClient;
    
    private CaptchaClient captchaClient1;

    @GetMapping("/captcha")
    public Object captcha() {
        LOGGER.info("生成二维码");
        try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            CaptchaBean captchaBean = captchaClient.generate();
            String capText = captchaBean.getResult();
            LOGGER.info("capText===================:"+capText);
            String uuid = UUID.randomUUID().toString();
            stringRedisTemplate.boundValueOps(uuid).set(capText,60, TimeUnit.SECONDS);
            BufferedImage bi = captchaBean.getBufferedImage();
            ImageIO.write(bi, "jpg", baos);
            String imgBase64 = Base64.encodeBase64String(baos.toByteArray());

            return ResponseEntity.ok()
                    .header("Access-Control-Allow-Origin","*")
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(
                            ImmutableMap.of("data", ImmutableMap.of(uuid,"data:image/jpeg;base64,"+imgBase64)
                                    ,"code", 200
                                    ,"msg", "成功！"
                                    ,"timestamp", System.currentTimeMillis())
                    );
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(),e);
        }
    }
    
    
    @GetMapping("/captcha2")
    public void captcha2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        LOGGER.info("生成二维码");
        
        if(captchaClient1 == null) {
        	CaptchaClient.Builder builder = new CaptchaClient.Builder();
            captchaClient1 = builder.captchaStrategy(new ChineseCaptchaStrategy()).build();
            // CalculateCaptchaStrategy // ChineseCaptchaStrategy
        }
        
        String ipAddress = request.getParameter("ip");
        ipAddress = ClientRequestInfoUtil.getClientIp(request)+ ipAddress;
        
        // 同一个ip地址10分钟内限制获取图片验证码的次数限制为5次
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
        String timeStr = LocalDateTime.now().format(formatter);
        
        LOGGER.debug("客户端["+ipAddress+"]获取的验证码请求次数:");
        int queryCnt = 0;
		Set<String> keys = stringRedisTemplate.keys(ipAddress+"*");
		LOGGER.debug("[");
		if(keys != null) {
			Iterator<String> it = keys.iterator();
			while(it.hasNext()) {
				String tmsKey = it.next();
				String timeMun = stringRedisTemplate.boundValueOps(tmsKey).get();
				if(timeMun != null && timeMun.trim().length() > 0) {
					LOGGER.debug(timeMun);
					queryCnt = queryCnt + Integer.parseInt(timeMun);
				}
			}
		}
		LOGGER.debug("]");
		 
		
        LOGGER.debug("客户端["+ipAddress+"]10分钟内已经请求了["+queryCnt+"]次");
        
        if(queryCnt > 5) {
        	throw new RuntimeException("每台电脑10分钟内最多获取5次验证码");
        }
        
        
        
        CaptchaBean captchaBean = captchaClient1.generate();
        String capText = captchaBean.getResult();
        System.out.println("-----------------------------------");
        System.out.println(capText);
        System.out.println("-----------------------------------");
        String uuid = UUID.randomUUID().toString();
        stringRedisTemplate.boundValueOps(uuid).set(capText,60, TimeUnit.SECONDS);
        BufferedImage bi = captchaBean.getBufferedImage();
        
        //BufferedImage 转 InputStream
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);
        ImageIO.write(bi, "png", imageOutput);
        InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        long length = imageOutput.length();
        
        //设置response
        response.setContentType("application/x-msdownload");
        response.setContentLength((int)length);
       String imageName = System.currentTimeMillis()+".jpg";
        response.setHeader("Content-Disposition","attachment;filename="+imageName);
        
        //输出流
        byte[] bytes = new byte[1024];
        OutputStream outputStream = response.getOutputStream();
        long count = 0;
        while(count < length){
            int len = inputStream.read(bytes, 0, 1024);
            count +=len;
            outputStream.write(bytes, 0, len);
        }
        outputStream.flush();
        outputStream.close();
        inputStream.close();
        byteArrayOutputStream.close();
        
        String currentCacheTimes = stringRedisTemplate.boundValueOps(ipAddress+timeStr).get();
        if(currentCacheTimes != null && currentCacheTimes.trim().length() > 0) {
        	stringRedisTemplate.boundValueOps(ipAddress+timeStr).increment(1);
        }else {
        	stringRedisTemplate.boundValueOps(ipAddress+timeStr).set("1",10, TimeUnit.MINUTES);
        }
        
        
  
        
    }
        
    
    
    
    
}
